import Vue from 'vue';
import { MessageBox } from 'element-ui';
import pages from '@/generated/pages';
import { savePageActivityRecord } from './page-activity-recorder';
import qs from 'qs';

export default {
  mounted() {
    this.$refs.tabs.$on('activeTabChange', (activeTabKey) => {
      this.setOtherPagePause(activeTabKey);
      this.$refs.tabs.getTabPaneComponents().forEach((tabPane) => {
        if (tabPane.name == activeTabKey) {
          let pageComponent = tabPane.$children[0];
          if (pageComponent._pageState == 'paused') {
            if (pageComponent.onPageResume) {
              pageComponent.onPageResume();
            }
            pageComponent._pageState = 'active';

            savePageActivityRecord({
              pageKey: activeTabKey,
              eventType: 'resumed'
            });
          }
        }
      });
    });

    this.$refs.tabs.$on('remove', (tabKey) => {
      savePageActivityRecord({
        pageKey: tabKey,
        eventType: 'removed'
      });
    });

    document.addEventListener('visibilitychange', () => {
      if (this.$refs.tabs == null) return;
      this.$refs.tabs.getTabPaneComponents().forEach((tabPane) => {
        let pageComponent = tabPane.$children[0];
        if (pageComponent && pageComponent.isCurrent) {
          if (!document.hidden) {
            if (pageComponent.onShow) {
              pageComponent.onShow();
            }
          } else {
            if (pageComponent.onHide) {
              pageComponent.onHide();
            }
          }
        }
      });
    });

    // 兼容老版本api
    window.openModuleByCode = (code, options) => {
      var node = Object.assign({}, findFunc(this.$refs.navMenu.menuTreeNodes, code));
      this.oldApiOpenPageBridge(node, options);
      function findFunc(nodes, code) {
        for (var i in nodes) {
          var node = nodes[i];
          if (node.attributes && node.attributes.code && node.attributes.code.toString() == code)
            return node;
          node = findFunc(node.children, code);
          if (node)
            return node;
        }
        return null;
      }
    };
  },
  methods: {
    /* 打开一个标签页承载一个页面，这个方法现在被NavMenu，以及原使用easyui代码的方法调用 */
    oldApiOpenPageBridge(node, options) {
      let { url } = node.attributes;

      let searchIndex = url.lastIndexOf('?');
      let search = searchIndex == -1 ? '' : url.substr(searchIndex);
      let path = searchIndex == -1 ? url : url.substring(0, searchIndex);
      if (path.endsWith('.do')) {
        url = path + (!search ? "?" : search + "&");
        if (options && options.params)
          url += qs.stringify(options.params);
        if (!node.isNoNode)
          url += "&_func_id=" + node.id;

        this.openPage({
          path: path.substring(0, path.length - 3),
          type: 'iframe',
          title: node.text,
          parentTabKey: options ? options.parentTabKey : null,
          extras: {
            iframeAttrs: {
              id: (node.attributes.code ? 'module-iframe-' + node.attributes.code : ''),
              src: url
            },
            ...options
          }
        });
      } else if (path.startsWith('http') && !path.endsWith(".do")) {
        window.open(path);
      } else if (path.startsWith('/')) {
        this.openPage({
          path,
          params: qs.parse(search.substring(1)),
          title: node.text
        });
      } else if (path.startsWith('redirect=')) {
        this.openPage({
          path: path.substring('redirect='.length, searchIndex),
          params: qs.parse(search.substring(1))
        });
      } else {
        window.open(path + ".do" + search, new Date().getTime());
      }
    },
    openPage(options) {
      const { path } = options;
      if (!path) {
        return;
      }

      if (options.type != 'iframe') {
        this.pushPage(options);
      } else {
        const { tabs } = this.$refs;
        const tabKey = path + (options.key ? '__' + options.key : '');
        if (tabs.findTabByKey(tabKey)) {
          tabs.activeTabKey = tabKey;
          options.extras && options.extras.onLoad && options.extras.onLoad();
          return;
        }
        let tab = {
          title: options.title,
          key: tabKey,
          content: {
            render(h) {
              return h('iframe', {
                attrs: options.extras.iframeAttrs,
                style: `visibility:hidden;display: block;overflow:auto;
                  width:100%;height:100%;margin:0px;outline: none;border-width:0px;`
              });
            },
            mounted() {
              this.$el.contentWindow.addEventListener('load', () => {
                this.$el.style.visibility = 'visible';
                tab.loading = false;
                options.extras && options.extras.onLoad && options.extras.onLoad();
              });

              // 监听iframe内部的事件并转发给外层顶级窗口
              ['keydown', 'keyup', 'click'].forEach((eventType) => {
                this.$el.contentWindow.addEventListener(eventType, (event) => {
                  window.document.dispatchEvent(new CustomEvent(eventType, {detail: event}));
                });
              });
            }
          },
          loading: true,
          parentTabKey: options && options.parentTabKey,
          options
        };
        tabs.addTab(tab);
        tabs.activeTabKey = tab.key;

        if (!options.autostart) {
          savePageActivityRecord({
            pageKey: tabKey,
            eventType: 'created'
          });
        }
      }
    },
    pushPage(options) {
      if (typeof options == 'string') {
        options = { path: options };
      }

      // 兼容末尾带'/index'的旧方式
      if (options.path.endsWith('/index')) {
        options.path = options.path.substring(0, options.path.length - '/index'.length);
      }

      const { path } = options;
      const { tabs } = this.$refs;  

      // path + 可选的key 作为tab的key
      const tabKey = path + (options.key ? '__' + options.key : '');
      // 根据key检查该tab是否已经打开
      if (tabs.findTabByKey(tabKey)) {
        // 如果之前已经打开了，则现在选中该tab
        tabs.activeTabKey = tabKey;
        
        this.$refs.tabs.getTabPaneComponents().forEach((tabPane) => {
          let pageComponent = tabPane.$children[0];
          if (tabPane.name == tabKey) {
            pageComponent._params = options.params;
          }
        });
      } else {
        const page = pages[path];
        if (!page) {
          this.$message.error(`错误：未找到指定页面：${path}，请联系开发者`);
          return;
        }
        let tab = {
          title: options.title || '',
          key: tabKey,
          content: null, // vue组件
          loading: true, // vue组件加载状态
          parentTabKey: options.parentTabKey,
          options
        };
        
        tabs.addTab(tab);
        tabs.activeTabKey = tabKey;

        /* 异步加载组件，并设置为tab的content */
        page().then(({default: component}) => {
          /*
           组件类将实例化多次，使用不同的参数。
           所以下面的修改（包括mixins）必须基于原组件类对象，这里保证修改的是拷贝对象，下次使用的原对象是没有经过修改的
          */
          component = {...component};

          // 混入一些数据和方法
          (component.mixins = component.mixins || []).push({
            computed: {
              isCurrent() {
                return this._pageState == 'active';
              }
            },
            beforeCreate() {
              Vue.util.defineReactive(this, '_pageState', 'active');

              Vue.util.defineReactive(this, '_params', null); // null表示仅仅_params变量本身而不包括属性是响应式的
              this._params = options.params;
              this._pageOptions = options;
              this._pageOptions.params = this._params;
              Object.defineProperty(this, '$params', {
                get: () => this._params || {}
              });
              Object.defineProperty(this, '$pageOptions', {
                get: () => this._pageOptions
              });
            },
            methods: {
              pushPage: (options) => {
                if (typeof options == 'string') {
                  options = { path: options };
                }
                // 记录父tab
                options.parentTabKey = tab.key;
                this.pushPage(options);
              },
              openTab: (options) => {
                this.oldApiOpenPageBridge(
                  {
                    attributes: {url: options.url},
                    text: options.title,
                    isNoNode: true
                  },
                  {parentTabKey: tab.key}
                );
              },
              closeCurrentPage: this.closeCurrentPage.bind(this),
              reloadCurrentPage: this.reloadCurrentPage.bind(this)
            }
          })

          tab.content = component;
          let { title: pagePropsTitle } = component.pageProps || {};
          if (pagePropsTitle && typeof pagePropsTitle == 'function') {
            pagePropsTitle = pagePropsTitle({
              ...options,
              // 一些标题风格
              subTitle
            });
          }
          // 设置标题
          let title = (options.title || pagePropsTitle || '未定义标题');
          if (options.subTitle) {
            title = subTitle(options.subTitle, title);
          }
          tab.title = title;

          tab.loading = false;

          options.onPageLoad && options.onPageLoad();
        }).catch((e) => { //无网络或404
          console.error(e);
          MessageBox.confirm('功能页面加载失败，可能是因为版本已更新，现在刷新网页以加载更新版本吗？', '提示', {
            confirmButtonText: '好的',
            cancelButtonText: '稍后自行刷新网页',
            type: 'warning'
          }).then(() => {
            location.reload();
          });
        });

        if (!options.autostart) {
          savePageActivityRecord({
            pageKey: tabKey,
            eventType: 'created'
          });
        }
      }
    },
    setOtherPagePause(notPageName) {
      // 遍历除当前点击tab外的其它tab中的内容组件实例
      this.$refs.tabs.getTabPaneComponents().forEach((tabPane) => {
        if (tabPane.name != notPageName) {
          let pageComponent = tabPane.$children[0];
          if (pageComponent) {
            if (pageComponent._pageState == 'active') {
              if (pageComponent.onPagePause) {
                pageComponent.onPagePause();
              }
              pageComponent._pageState = 'paused';
            }
          }
        }
      });
    },
    closeCurrentPage() {
      this.$refs.tabs.removeActiveTab();
    },
    reloadCurrentPage() {
      this.$refs.tabs.execCommandForActiveCmd('reload');
    }
  },
}

function subTitle(sub, main) {
  return `${sub} - ${main}`;
}
